//=========================================================================
// Copyright (C) 2022 The C++ Component Model(COMO) Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//=========================================================================

#ifndef __MEMPOOL_H__
#define __MEMPOOL_H__

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

#define ALIGN4(v)       (((v) + 3) & ~3)
#define ALIGN8(v)       (((v) + 7) & ~7)

typedef enum {
	DONT_USE_MEM_POOL,
	MUST_USE_MEM_POOL,
	TRY_TO_USE_MEM_POOL
} TryToUseMemPool;

typedef struct tagCMemPool_Unit             // The type of the node of linkedlist.
{
    struct tagCMemPool_Unit *pPrev, *pNext;
} CMemPool_Unit;

typedef struct tagCMemPool
{
    void          *m_pMemBlock;              // The address of memory pool.
    bool           shouldFreeMemBlock;

    //Manage all unit with two linkedlist.
    CMemPool_Unit *m_pAllocatedMemBlock;     // Head pointer to Allocated linkedlist.
    CMemPool_Unit *m_pFreeMemBlock;          // Head pointer to Free linkedlist.

    size_t m_ulUnitSize;             // Memory unit size. There are much unit in memory pool.
    size_t m_ulBlockSize;            // Memory pool size. Memory pool is make of memory unit.
} CMemPool;

CMemPool *CMemPool_New();
CMemPool *CMemPool_New2(void *buffer, size_t lUnitNum, size_t lUnitSize);
void CMemPool_Delete(CMemPool *this);

void *CMemPool_Alloc(CMemPool *this, size_t ulSize, TryToUseMemPool iTryToUseMemPool);
void CMemPool_Free(CMemPool *this, void *p);
bool CMemPool_CheckExist(CMemPool *this, void *p);
bool CMemPool_CheckFull(CMemPool *this);
bool CMemPool_SetBuffer(CMemPool *this, void *buffer, size_t ulUnitNum, size_t ulUnitSize);


typedef struct tagMemPoolItem {
    size_t      lUnitNum;
    size_t      lUnitSize;
    CMemPool   *memPool;
} MemPoolItem;

typedef struct tagCMemPoolSet
{
    MemPoolItem    *m_MemPoolSet;
    size_t          m_ItemNum;

    // general purpose memory pool
    CMemPool       *g_MemPool;
    size_t          m_g_lUnitNum;
    size_t          m_g_lUnitSize;

    MemPoolItem    *m_g_MemPoolSet;
} CMemPoolSet;

CMemPoolSet *CMemPoolSet_New(MemPoolItem *memPoolItems, size_t num);
CMemPoolSet *CMemPoolSet_New2(MemPoolItem *memPoolItems, size_t num, size_t g_lUnitNum, size_t g_lUnitSize);
void CMemPoolSet_Delete(CMemPoolSet *this);

void *CMemPoolSet_Alloc(CMemPoolSet *this, size_t ulSize, TryToUseMemPool iTryToUseMemPool);
bool CMemPoolSet_Free(CMemPoolSet *this, void *p);

bool CMemPoolSet_CreateGeneralMemPool(CMemPoolSet *this, size_t lUnitNum, size_t lUnitSize);

#ifdef __cplusplus
}  // extern C
#endif

#endif //__MEMPOOL_H__
